import { setStyle, transitionend } from './const';
import { touch } from './touch';
const noop = function () { };

/**
 * 移动端轮播 
 * @param {object|string} selector 轮播容器
 * @param {boolean} autoplay 自动播放 
 * @param {number} speed 自动播放的速度
 * @param {boolean} loop 首尾无缝连接
 * @param {boolean} compatible 当浏览器不支持Css3 Transform ransition时，提供相应的兼容方案，目前没有实现相应的功能
 * @param {string} direction 轮播方向，默认x轴上
 * @param {string|number} threshold 手指混动的距离大于这个值时自动过渡到下一个滑块
 * @param {string} transition Css过渡样式
 * @param {function} onjumpstart 滑块开始移动之前
 * 
 * @desc 
 * 1.自动轮播  定时器  无缝衔接  动画结束瞬间定位 
 * 2.手指滑动的时候让轮播图滑动   touch事件  记录坐标轴的改变 改变轮播图的定位（位移css3）
 * 3.当滑动的距离不超过一定的距离的时候  需要吸附回去  过渡的形式去做
 * 4.当滑动超过了一定的距离  需要 跳到 下一张或者上一张  （滑动的方向） 一定的距离（默认: 屏幕的三分之一）
 * 5.开发测试阶段使用alert弹层，警告测试者
 * 
 * @desc 自动播放相关的 API 全部受配置项 autoplay 控制，当 autoplay 为 false时，相关的 API 在调用之后无任何效果
 * @method init(opts) 初始化，需要传入一个配置项对象
 * @method start() 启动
 * @method restart() 重启
 * @method stop() 关闭
 * 
 * @desc 实现思路
 *       index ++ 
 * 
 */
export class Carousel {
    constructor(opts) {
        //************************ 注册自身属性

        // 配置项 
        this.selector = null;
        this.autoplay = null;
        this.speed = null;
        this.loop = null;
        this.threshold = null;
        this.direction = null;
        this.transition = null;
        this.onjumpstart = null;
        this.compatible = null;

        // 属性变量 
        this._timer = null;         // 定时器引用  
        this._times = null;         // 轮播的圈数，所有slider都过一遍算一圈
        this.dElement = null;       // 容器
        this.dMovement = null;      // 运动盒子 
        this.dCurrMovement = null;  // 当前的移动盒子 
        this.size = null;           // 滑块的数量
        this.index = null;          // 滑块的下标 
        this.xStep = null;          // x方向步进
        this.yStep = null;          // y方向步进
        this.cStep = null;          // 当前使用的滑块的步进距离 cStep <==> current step 
    }

    /**
     * 初始化
     * @param {object} opts 
     */
    init(opts) {
        if (!opts || 'object' !== typeof opts) {
            throw new Error('配置项必须是一个纯对象');
        }

        const { DEFAULT } = Carousel;

        // options
        this.selector = 'string' === typeof opts.selector ? opts.selector : DEFAULT.selector;
        this.autoplay = opts.autoplay === false ? opts.autoplay : DEFAULT.autoplay;
        this.loop = opts.loop === false ? opts.loop : DEFAULT.loop;
        this.speed = 'number' === typeof opts.speed ? opts.speed : DEFAULT.speed;
        this.compatible = 'function' === opts.compatible ? opts.compatible : DEFAULT.compatible;
        this.threshold = opts.threshold || DEFAULT.threshold;
        this.direction = 'y' === typeof opts.direction ? 'y' : DEFAULT.direction;
        this.transition = 'string' === typeof opts.transition ? opts.transition : DEFAULT.transition;
        this.onjumpstart = 'function' === typeof opts.onjumpstart ? opts.onjumpstart : DEFAULT.onjumpstart;

        // variable
        this.dElement = document.querySelectorAll(this.selector)[0];
        this.dMovement = this.dElement.children[0];
        this.dCurrMovement = this.dMovement;
        this.size = this.dMovement.children.length;
        this.index = 0;
        this.xStep = this.dElement.offsetWidth || this.dElement.clientWidth;
        this.yStep = this.dElement.offsetHeight || this.dElement.offsetHeight;
        this.cStep = this.direction === 'x' ? this.xStep : this.yStep;
        this._times = 0;

        // event
        // touch({ selector: this.dElement, onstart: touchstart, onmove: touchmove, onend: touchend });

        // autoplay
        this.start();
        this._layout();
    }

    /** 
     * 自动播放: 启动  
     **/
    start() {
        console.assert(this.autoplay === true, '[Carousel] Autoplay');
        this.autoplay && this._autoplay(false, this._jump.bind(this));
    }

    /** 
     * 自动播放: 重启 
     **/
    restart() {
        console.assert(this.autoplay === true, '[Carousel] Autoplay');
        this.autoplay && this._autoplay(true, this._jump.bind(this));
    }

    /** 
     * 自动播放: 停止 
     **/
    stop() {
        console.assert(this.autoplay === true, '[Carousel] Autoplay');
        this.autoplay && this._timer && this._autoplay(true);
    }

    /**
     * 自动播放
     * 
     * @param {boolean} isStop 停止
     * @param {function} callback 回调
     * @private
     */
    _autoplay(isStop, callback) {
        // 停止
        if (isStop && this._timer) {
            clearInterval(this._timer);
            this._timer = null;
            'function' === typeof callback && callback();
            return;
        }

        function interval() {
            'function' === typeof callback && callback();
        }

        // 开启
        this._timer = setInterval(interval, this.speed);
    }

    /**  
     * 无缝复制 
     **/
    _layout() {
        console.assert(this.loop === true, '[Carousel] Loop');
        console.assert(this.size > 0, '[Carousel] Sliders Max Conut');
        if (this.loop && this.size) {
            const dSelf = this.dMovement;
            const dNext = dSelf.nextElementSibling;
            const dCopy = dSelf.cloneNode(true);
            const dWarp = document.createElement('div');
            setStyle(dSelf, {
                position: 'absolute',
                top: 0,
                left: 0,
                width: '100%'
            });  
            setStyle(dCopy, {
                transform: `translate(${this.cStep}px, 0) translateZ(0)`
            });
            dWarp.style.cssText = 'position:relative;overflow:hidden;width:100%;height:100%;';

            dWarp.appendChild(dSelf);
            dWarp.appendChild(dCopy);
            if (dNext) {
                this.dElement.insertBefore(dWarp, dNext);
            } else {
                this.dElement.appendChild(dWarp);
            }
        }
    }

    /** 
    * 前往指定的滑块
    *  
    **/
    _jump() {
        this.index++;
        let index = this.index;

        if (this.index >= this.size) {
            this._times++;
            this.index = 0;
        }
        
        let distance = this.index * this.cStep;

        // 响应滑动开始事件
        this.onjumpstart.call(this);

        if (this._times > 0 && index === this.size) {
            const dOldMovement = this.dCurrMovement;
            
            setStyle(dOldMovement, {
                transition: this.transition,
                transform: `translate(${-index * this.cStep}px, 0) translateZ(0)`
            });

            var timer = setTimeout(function(){
                clearTimeout(timer);
                timer = null;
                setStyle(dOldMovement, {
                    transition: 'none',
                    transform: `translate(${this.cStep}px, 0) translateZ(0)`
                });
            }.bind(this), this.speed); 
            
            this.dCurrMovement = this._times % 2 === 1 ? this.dMovement.nextElementSibling : this.dMovement;
        }

        setStyle(this.dCurrMovement, {
            transition: this.transition,
            transform: `translate(${-distance}px, 0) translateZ(0)`
        });
    }
};

// 默认配置项
Carousel.DEFAULT = {
    selector: null,
    autoplay: true,
    loop: true,
    speed: 2000,
    compatible: false,
    threshold: '50%',
    direction: 'x',
    transition: 'transform 500ms',
    onjumpstart: noop
};
